其他
.NET 6 新特性Controller支持 IAsyncDisposable
前言
.NET中拥有非托管资源的类通常会实现IDisposable接口,以提供一种同步释放非托管资源的机制。但是,在某些情况下,需要提供一种异步机制来释放非托管资源,这时候可以实现IAsyncDisposable
接口。
在实现此接口后,将使用DisposeAsync方法来释放这些非托管资源。但是在.NET 6之前,即使Controller实现了IAsyncDisposable接口,也不会执行DisposeAsync方法。
下面,让我们来验证一下。
示例
1、.NET 5.0
使用VS 2019创建基于.NET 5.0框架的Web API项目,然后修改WeatherForecastController代码,实现IAsyncDisposable接口:
public class WeatherForecastController : ControllerBase, IAsyncDisposable
{
[ApiExplorerSettings(IgnoreApi = true)]
public ValueTask DisposeAsync()
{
throw new NotImplementedException();
}
}public class WeatherForecastController : ControllerBase, IAsyncDisposable
{
[ApiExplorerSettings(IgnoreApi = true)]
public async ValueTask DisposeAsync()
{
_logger.LogInformation($"{DateTime.Now} Begin DisposeAsync");
await Task.Delay(3000);//模拟异步释放非托管资源
_logger.LogInformation($"{DateTime.Now} End DisposeAsync");
}
}
加上ApiExplorerSettings
是为了避免swagger报错。执行请求,发现并没有抛出异常,说明没有执行DisposeAsync方法。而当我们实现IDisposable接口后,再次执行请求,会执行Dispose方法抛出异常,说明Controller确实被释放了:
2、.NET 6.0
使用VS 2022创建基于.NET 6.0框架的Web API项目,然后修改WeatherForecastController代码,实现IAsyncDisposable接口:
public class WeatherForecastController : ControllerBase, IAsyncDisposable
{
[ApiExplorerSettings(IgnoreApi = true)]
public async ValueTask DisposeAsync()
{
_logger.LogInformation($"{DateTime.Now} Begin DisposeAsync");
await Task.Delay(3000);//模拟异步释放非托管资源
_logger.LogInformation($"{DateTime.Now} End DisposeAsync");
}
}
运行效果如下,执行了DisposeAsync方法:
总结
最好同时实现IDisposable和IAsyncDisposable接口,确保释放资源:
[ApiExplorerSettings(IgnoreApi = true)]
public void Dispose()
{
_logger.LogInformation($"{DateTime.Now} Begin Dispose");
Dispose(disposing: true);
_logger.LogInformation($"{DateTime.Now} End Dispose");
}
[ApiExplorerSettings(IgnoreApi = true)]
public async ValueTask DisposeAsync()
{
_logger.LogInformation($"{DateTime.Now} Begin DisposeAsync");
await Task.Delay(3000);//模拟异步释放非托管资源
Dispose(disposing: false);
_logger.LogInformation($"{DateTime.Now} End DisposeAsync");
}
protected void Dispose(bool disposing)
{
if (disposing)
{
Thread.Sleep(3000);//模拟同步释放非托管资源
}
_logger.LogInformation($"{DateTime.Now} Dispose {disposing}");
}
- EOF -
看完本文有收获?请转发分享给更多人
推荐关注「DotNet」,提升.Net技能
点赞和在看就是最大的支持❤️